
float G_BlinnPhong_Implicit( /* const in float dotNL, const in float dotNV */) {

	// geometry term is (n dot l)(n dot v) / 4(n dot l)(n dot v)
	return 0.25;

}

float D_BlinnPhong( const in float shininess, const in float dotNH ) {

	return RECIPROCAL_PI * (shininess * 0.5 + 1.0) * pow(dotNH, shininess);

}

vec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {

	vec3 halfDir = normalize(lightDir + viewDir);

	float dotNH = saturate(dot(normal, halfDir));
	float dotVH = saturate(dot(viewDir, halfDir));

	vec3 F = F_Schlick(specularColor, 1.0, dotVH);

	float G = G_BlinnPhong_Implicit( /* dotNL, dotNV */);

	float D = D_BlinnPhong(shininess, dotNH);

	return F * (G * D);

} // validated
